<?php
namespace Library;

class Platform
{
    const PRODUCTION = 'production';
    const TESTING = 'testing';
    
    private static $_initialized = false;
    private static $_autoloader;
    private static $_applicationInstances = array();
    
    private static $_default_settings = array(
        'layout' => array(
            'auto_render' => true
        ),
        'application' => array(
            'default_controller' => 'Main',
            'default_action' => 'index'
        )
    );
    
    private static function _initialize()
    {
		//Run output handler
		ob_start();
        
        //Register autoloader and error handlers
		self::$_autoloader = new Autoloader();
		
		spl_autoload_register(array(self::$_autoloader, 'autoload'));
		set_error_handler(function($errno, $errstr, $errfile, $errline ) {
		    throw new \ErrorException($errstr, $errno, 0, $errfile, $errline);
		});
    }
    
    public static function call($object, $method, $arguments)
    {
        switch(count($arguments))
        {
            case 0:
                $result = $object->$method();
                break;
            case 1:
                $result = $object->$method($arguments['0']);
                break;
            case 2:
                $result = $object->$method($arguments['0'], $arguments['1']);
                break;
            case 3:
                $result = $object->$method($arguments['0'], $arguments['1'], $arguments['2']);
                break;
            case 4:
                $result = $object->$method($arguments['0'], $arguments['1'], $arguments['2'], $arguments['3']);
                break;
            case 5:
                $result = $object->$method($arguments['0'], $arguments['1'], $arguments['2'], $arguments['3'], $arguments['4']);
                break;
            default:
                $result = call_user_func_array(array($object, $method), $arguments);
                break;
        }
        
        return $result;
    }
    
    public static function getAutoloader()
    {
        return self::$_autoloader;
    }
    
    public static function getConfig($namespace = null)
    {        
        $app = $namespace == null ? end(self::$_applicationInstances) : self::_getApplication($namespace);
        
        if ($app == null)
        {
            throw new \Exception('Application with namespace ' . $namespace . ' does not exist.');
        }
        
        return $app->getConfig();
    }
    
    public static function merge($array1, $array2)
    {
        foreach($array2 as $key => $value)
        {
            if (is_array($value) && isset($array1[$key]))
            {
                $array1[$key] = self::merge($array1[$key], $array2[$key]);
                continue;
            }
            
            $array1[$key] = $value;
        }
        
        return $array1;
    }
    
    private static function _getApplication($module)
    {
        return isset($this->_applicationInstances[$module]) ? $this->_applicationInstances[$module] : null;
    }
    
    public static function createApplication($options)
    {
        if (!self::$_initialized)
        {
            self::_initialize();
        }
        
        if (!isset($options['namespace']) || !isset($options['path']))
        {
            throw new \Exception('Unable to create new application instance namespace or path is missing.');
        }
        
        $settings = self::$_default_settings;
        $settings['application']['namespace'] = $options['namespace'];
        $settings['application']['path'] = $options['path'];
        
        if (!file_exists($options['path'] . '/config/settings.ini'))
		{
			throw new \Exception('Settings file ' . $options['path'] . '/config/settings.ini does not exist.');
		}
		
        $ini = new \Library\Config\Ini($options['path'] . '/config/settings.ini');
        $app = new \Library\Application(self::merge($settings, $ini->getData()));
        
        self::$_applicationInstances[$options['namespace']] = $app;
        
        return $app;
    }
    
    public static function setEnv($env)
    {
        switch($env)
        {
            case self::PRODUCTION:
                error_reporting(-1);
                ini_set('display_errors', '0');
                break;
            case self::TESTING:
                error_reporting(E_ALL);
                ini_set('display_errors', '1');
                break;
        }
    }
}